"""
ConnLLM V2 HTTP客户端
提供HTTP请求功能
"""

from typing import Dict, Any, Optional, Generator, Union, Tuple
import logging
import json
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

logger = logging.getLogger("connllm.core_v2.http")

class HTTPClientV2:
	"""HTTP客户端V2实现"""
	
	def __init__(self, base_url: str, default_headers: Dict[str, str] = None,
				timeout: int = 60, proxy: Optional[str] = None):
		"""
		初始化HTTP客户端
		
		Args:
			base_url: 基础URL
			default_headers: 默认头部
			timeout: 超时时间（秒）
			proxy: 代理服务器
		"""
		self.base_url = base_url.rstrip("/")
		self.default_headers = default_headers or {}
		self.timeout = timeout
		self.proxy = proxy
		
		# 创建会话
		self.session = self._create_session()
		
	def request(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None,
			   headers: Optional[Dict[str, str]] = None) -> requests.Response:
		"""
		发送HTTP请求
		
		Args:
			method: HTTP方法
			endpoint: API端点
			data: 请求数据
			headers: 请求头部
			
		Returns:
			HTTP响应
			
		Raises:
			requests.RequestException: 请求失败时
		"""
		url = self._build_url(endpoint)
		merged_headers = self._merge_headers(headers)
		
		# 记录请求
		logger.debug(f"HTTP请求: {method} {url}")
		logger.debug(f"请求头部: {json.dumps(merged_headers, ensure_ascii=False, indent=2)}")
		if data:
			logger.debug(f"请求数据: {json.dumps(data, ensure_ascii=False, indent=2)}")
		
		# 发送请求
		start_time = time.time()
		try:
			response = self.session.request(
				method=method,
				url=url,
				json=data,
				headers=merged_headers,
				timeout=self.timeout,
				proxies=self._get_proxies()
			)
			
			# 检查响应状态
			response.raise_for_status()
			
			# 记录响应
			elapsed = time.time() - start_time
			logger.debug(f"HTTP响应: {response.status_code}, 耗时: {elapsed:.2f}秒")
			
			return response
			
		except requests.RequestException as e:
			elapsed = time.time() - start_time
			error_msg = f"HTTP请求失败: {str(e)}, 耗时: {elapsed:.2f}秒"
			
			# 获取更多错误信息
			if hasattr(e, 'response') and e.response is not None:
				try:
					error_content = e.response.text
					error_msg += f"\n响应内容: {error_content}"
				except Exception:
					pass
			
			logger.error(error_msg)
			raise
	
	def stream(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None,
			  headers: Optional[Dict[str, str]] = None) -> Generator[bytes, None, None]:
		"""
		发送HTTP流式请求
		
		Args:
			method: HTTP方法
			endpoint: API端点
			data: 请求数据
			headers: 请求头部
			
		Returns:
			响应块生成器
			
		Raises:
			requests.RequestException: 请求失败时
		"""
		url = self._build_url(endpoint)
		merged_headers = self._merge_headers(headers)
		
		# 记录请求
		logger.debug(f"HTTP流式请求: {method} {url}")
		if data:
			logger.debug(f"请求数据: {json.dumps(data, ensure_ascii=False, indent=2)}")
		
		# 发送请求
		start_time = time.time()
		try:
			with self.session.request(
				method=method,
				url=url,
				json=data,
				headers=merged_headers,
				timeout=self.timeout,
				proxies=self._get_proxies(),
				stream=True
			) as response:
				response.raise_for_status()
				
				# 记录响应开始
				logger.debug(f"HTTP流式响应开始: {response.status_code}")
				
				# 返回响应块
				for chunk in response.iter_content(chunk_size=None):
					if chunk:
						yield chunk
				
				# 记录响应结束
				elapsed = time.time() - start_time
				logger.debug(f"HTTP流式响应结束，耗时: {elapsed:.2f}秒")
				
		except requests.RequestException as e:
			elapsed = time.time() - start_time
			logger.error(f"HTTP流式请求失败: {str(e)}, 耗时: {elapsed:.2f}秒")
			raise
	
	def set_header(self, key: str, value: str):
		"""
		设置默认头部
		
		Args:
			key: 头部键
			value: 头部值
		"""
		self.default_headers[key] = value
	
	def _build_url(self, endpoint: str) -> str:
		"""
		构建完整URL
		
		Args:
			endpoint: API端点
			
		Returns:
			完整URL
		"""
		if endpoint.startswith("http"):
			return endpoint
			
		endpoint = endpoint.lstrip("/")
		return f"{self.base_url}/{endpoint}"
	
	def _merge_headers(self, headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
		"""
		合并默认头部和请求头部
		
		Args:
			headers: 请求头部
			
		Returns:
			合并后的头部
		"""
		merged = self.default_headers.copy()
		if headers:
			merged.update(headers)
		return merged
	
	def _get_proxies(self) -> Optional[Dict[str, str]]:
		"""
		获取代理配置
		
		Returns:
			代理配置字典
		"""
		if not self.proxy:
			return None
			
		return {
			"http": self.proxy,
			"https": self.proxy
		}
	
	def _create_session(self) -> requests.Session:
		"""
		创建请求会话
		
		Returns:
			请求会话
		"""
		session = requests.Session()
		
		# 设置重试策略
		retries = Retry(
			total=3,
			backoff_factor=0.5,
			status_forcelist=[429, 500, 502, 503, 504],
			allowed_methods=["GET", "POST"]
		)
		
		# 添加适配器
		adapter = HTTPAdapter(max_retries=retries)
		session.mount("http://", adapter)
		session.mount("https://", adapter)
		
		return session
